//
//  DTMConverter.cpp
//  dtm-converter
//
//  Created by Giorgio Tino on 3/3/14.
//  Copyright (c) 2014 Giorgio Tino. All rights reserved.
//

#include "DTMConverter.h"

#include <gl/glpng.h>
#include <plib/ul.h>
#include <plib/sg.h>
#include <plib/ssgLocal.h>

#define FILE_ROW_STRING_LENGTH 80

#define UNKNOWN -1
#define BLACK 0x0
#define WHITE 0xF

DTMConverter::~DTMConverter()
{
    
}

bool DTMConverter::convert(const char *input, const char *output)
{
    pngRawInfo rawInfo;
    
    int result = pngLoadRaw(input, &rawInfo);
    
    if(result == 0)
    {
        ulSetError(ulSeverity::UL_FATAL, "Error opening %s for reading.\n", input);
        return false;
    }
    
    FILE* fp = fopen(output, "wb");
    
    if(fp == NULL)
    {
        ulSetError(ulSeverity::UL_FATAL, "Error opening %s for writing.\n", output);
        return false;
    }
    
    printf("Width : %d\nHeight : %d\nDepth : %d\nAlpha : %d\nComponents : %d\n",rawInfo.Width,rawInfo.Height,rawInfo.Depth,rawInfo.Alpha, rawInfo.Components);
    
    unsigned int nPixels = rawInfo.Width * rawInfo.Height;
    unsigned int nBytes = ((rawInfo.Width * rawInfo.Depth + 7)>>3) * rawInfo.Height;
    unsigned int nValuesPerByte = (8 - rawInfo.Depth + 1);
    unsigned char color = BLACK; // 0 : black, 255 : white
    unsigned int count = 0;
    unsigned int bytes = 0;
    
    bool first = true;
    unsigned int iPixel = 0;
    unsigned int maxCount = 0;
    
    //
    // Main loop, RLE
    //
    for(int i = 0; i < nBytes; i++ )
    {
        unsigned char byte = rawInfo.Data[i];
        
        //_ssgWriteBytes(fp, 1, &byte);
        
        for(int j=0; j<nValuesPerByte; j++)
        {
            unsigned char value = (byte>>j) & 0x1;
            
            value = value > 0 ? WHITE : BLACK;
            
            if(first)
            {
                count = 1; // reset the RLE counter
                color = value; // set the new color
                
                first = false;
            }
            else if(color != value) // Switch/End!
            {
                bytes += _save(fp, color, rawInfo.Depth, count);
                
                maxCount = count > maxCount ? count : maxCount;
                
                count = 1; // reset the RLE counter
                color = value; // set the new color
            }
            else if(iPixel == nPixels-1)
            {
                count++;
                
                bytes += _save(fp, color, rawInfo.Depth, count);
            }
            else
            {
                count++;
            }
        }
        
        iPixel += nValuesPerByte;
    }
    
    if(fclose(fp) != 0)
    {
        ulSetError(ulSeverity::UL_FATAL, "Error closing %s.\n", output);
        
        return false;
    }
    
    printf("\nEstimated file size: %d bytes\nMax count : %d\n",bytes,maxCount);
    printf("Min raw size : %d bytes\n",(nPixels/8)+1+2);
    
    printf("\n");
    
    return true;
}

unsigned int DTMConverter::_save(FILE* fp, const unsigned int color, const unsigned int depth, const unsigned int count) const
{
    unsigned int hex = color == WHITE ? 0x8000 : 0x0000;
    unsigned int rleValue = hex | count;
    
    //
    // TODO : save to file
    //
    printf("%s (%d) : %x\n",color == BLACK ? "BLACK" : "WHITE",count,rleValue);
    
    _ssgWriteBytes(fp, 1, &rleValue);
    
    return count < 64 ? sizeof(unsigned char) * (8 - depth + 1) : sizeof(unsigned short) * (8 - depth + 1);
}
